﻿using System;
using System.Collections;
using System.Collections.Generic;
using Moq.Language.Flow;

namespace User.Global.Tests.Helper.MoqHelper
{
    /// <summary>
    /// Allgemeine Erweiterungen für das Moq Framework.
    /// Quellen:
    /// http://haacked.com/archive/2010/11/24/moq-sequences-revisited.aspx
    /// </summary>
    public static class MoqExtensions
    {
        /// <summary>
        ///  Festlegen einer Reihe von unterschiedlichen Rückgabewerten für eine Funktion.
        /// </summary>
        public static void ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup, params TResult[] results) where T : class
        {
            setup.Returns(new Queue<TResult>(results).Dequeue);
        }

        /// <summary>
        /// Festlegen einer Reihe von unterschiedlichen Rückgabewerten für eine Funktion. Unterstützt auch das Zurückgeben von Exceptions.
        /// </summary>
        public static void ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup, params object[] results) where T : class
        {
            var queue = new Queue(results);
            setup.Returns(() =>
            {
                var result = queue.Dequeue();
                if (result is Exception)
                {
                    throw result as Exception;
                }
                return (TResult)result;
            });
        }

        //Example Usage of the Extensions:
        //############################################
        //var mock = new Mock<ISomeInterface>();
        //mock.Setup(r => r.GetNext()).ReturnsInOrder(1, 2, new InvalidOperationException());

        //Console.WriteLine(mock.Object.GetNext());
        //Console.WriteLine(mock.Object.GetNext());
        //Console.WriteLine(mock.Object.GetNext()); // Throws InvalidOperationException
    }
}
